/*
 *
 * Copyright (c) 2001-2018 泛微软件.
 * 泛微协同商务系统,版权所有.
 * 
 */
package weaver.fna.invoice.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.Charsets;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import net.sf.json.JSONObject;
import sun.misc.BASE64Encoder;
import weaver.conn.RecordSet;
import weaver.fna.invoice.Constants;
import weaver.fna.invoice.common.FnaInvoiceCommon;
import weaver.general.BaseBean;
import weaver.general.Util;
import weaver.hrm.User;
import weaver.systeminfo.SystemEnv;

/**
 * @author zhangwj
 * @Jan 23, 2019
 */
@SuppressWarnings("unchecked")
public class HttpUtil {


	/**
	 * post
	 * @param url
	 * @param params
	 * @return
	 */
	public static Map<String,Object> post(String url, Map<String, String> params) {
		CloseableHttpClient cilent = HttpClients.createDefault();
		Map<String,Object> reponseMap = new HashMap<String,Object>();
		try {
			HttpPost post = postForm(url, params);
			reponseMap = invoke(cilent, post);		
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			try {
				cilent.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return reponseMap;
	}
	
	/**
	 * invoke
	 * @param httpclient
	 * @param httpost
	 * @return
	 */
	private static Map<String,Object> invoke(CloseableHttpClient httpclient,
			HttpUriRequest httpost) {

		Map<String,Object> returnMap = new HashMap<String,Object>();
		HttpResponse response = sendRequest(httpclient, httpost);
		String body = paseResponse(response);
		// 请求返回结果状态
		returnMap.put("statusCode", response.getStatusLine().getStatusCode()); 
		returnMap.put("response", body);
		return returnMap;
	}
	
	/**
	 * sendRequest
	 * @param httpclient
	 * @param httpost
	 * @return
	 */
	private static HttpResponse sendRequest(CloseableHttpClient httpclient,
			HttpUriRequest httpost) {

		HttpResponse response = null;
		try {
			response = httpclient.execute(httpost);
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return response;
	}

	/**
	 * paseResponse
	 * @param response
	 * @return
	 */
	private static String paseResponse(HttpResponse response) {

		HttpEntity entity = response.getEntity();

		String body = null;
		try {
			body = EntityUtils.toString(entity, "UTF-8");
		} catch (ParseException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return body;
	}
	
	/**
	 * 获取  HttpPost 对象
	 * @param url
	 * @param params
	 * @return
	 */
	private static HttpPost postForm(String url, Map<String, String> params) {

		HttpPost httpost = new HttpPost(url);
		RequestConfig requestConfig = RequestConfig.custom()
				.setConnectTimeout(120000).setConnectionRequestTimeout(120000)
				.setSocketTimeout(120000).build();
		httpost.setConfig(requestConfig);

		if(params!=null){
			List<NameValuePair> nvps = new ArrayList<NameValuePair>();
			Set<String> keySet = params.keySet();
			for (String key : keySet) {
				nvps.add(new BasicNameValuePair(key, params.get(key)));
			}
			httpost.setEntity(new UrlEncodedFormEntity(nvps, Charsets.UTF_8));
		}
		return httpost;
	}
	
	/**
	 * Base64 加密
	 * @param str
	 * @return
	 */
    public static String getBase64(String str) {  
        byte[] b = null;  
        String s = "";  
        try {  
            b = str.getBytes("UTF-8");  
        } catch (UnsupportedEncodingException e) {  
            e.printStackTrace();  
        }  
        if (b != null) {  
            s = new BASE64Encoder().encode(b);  
        }  
        return s;  
    }  
    
    
    public static JSONObject postImage(byte[] bytes,User user){
		new BaseBean().writeLog("开始调用发票识别接口...");
		RecordSet rs = new RecordSet();
		JSONObject jsonObject = new JSONObject();
		HttpURLConnection connection = null;
		OutputStream outputStream = null;


		boolean existEffectOcr=false;
		boolean existEffectCloud=false;
		int imageCatalog = 0;
		//ocr
		String interfaceurl = "";
		String appKey = "";
		String secret = "";
		//Cloud
		String cid = "";
		String ocrUrl = "";
		String uploadFileUrl = "";
		String tokenUrl = "";
		String userName = "";
		String password = "";
		try {
			JSONObject interfaceInfo = InvoiceCloudUtil.getInterfaceInfo(user, true, false, true);
			JSONObject cloudInfo = interfaceInfo.getJSONObject("cloud");
			JSONObject ocrInfo = interfaceInfo.getJSONObject("ocr");
			existEffectCloud = cloudInfo.getBoolean("existEffectCloud");
			existEffectOcr = ocrInfo.getBoolean("existEffectOcr");
			if(existEffectCloud){
				imageCatalog = cloudInfo.getInt("imageCatalog");
				 cid = cloudInfo.getString("cid");
				 ocrUrl = cloudInfo.getString("ocrUrl");
				 tokenUrl = cloudInfo.getString("tokenUrl");
				 uploadFileUrl = cloudInfo.getString("uploadFileUrl");
				 userName = cloudInfo.getString("userName");
				 password = cloudInfo.getString("password");
			}else if(existEffectOcr){
				imageCatalog = ocrInfo.getInt("imageCatalog");
				interfaceurl = ocrInfo.getString("interfaceurl");
				appKey = ocrInfo.getString("appKey");
				secret = ocrInfo.getString("secret");
			}
			if(!existEffectCloud && !existEffectOcr){
				throw new Exception(SystemEnv.getHtmlLabelName(520791, user.getLanguage()));//后台【预算】-【发票管理】-【发票接口配置】未配置生效的票据接口！
			}
			if(imageCatalog==0){
				throw new Exception("发票识别接口未配置发票图片目录");
			}

			if(existEffectCloud){
				JSONObject resultJsonObj = InvoiceCloudUtil.invoiceOCR(bytes, cid, ocrUrl,tokenUrl,uploadFileUrl, user, userName, password);
				jsonObject.put("status", resultJsonObj.get("status"));
				jsonObject.put("returnInfo", resultJsonObj.getJSONObject("returnInfo"));
			}else{
				jsonObject = invoiceOCR(appKey,secret,interfaceurl,bytes,connection,outputStream);
			}
		} catch (Exception e) {
			jsonObject.put("status", Constants.ERROR_CODE);
			jsonObject.put("errMsg", e.getMessage());
		}finally {
			if(connection!=null){
				connection.disconnect();
			}
		}
		FnaInvoiceCommon.addFnainvoiceLog("1",bytes,"","","","","",
				jsonObject, user, "OCR",appKey);
		new BaseBean().writeLog("结束调用发票识别接口...");
		new BaseBean().writeLog("jsonObject:"+jsonObject.toString());
		return jsonObject;
	}


	private static JSONObject invoiceOCR(String appKey,String secret,String interfaceurl,byte[] bytes,
										 HttpURLConnection connection,OutputStream outputStream) throws Exception {
		JSONObject resultJsonObj = new JSONObject();
		Map<String, Object> params = new LinkedHashMap<String, Object>();
		String timestamp = System.currentTimeMillis() / 1000 +"";

		String type="0";
		String token=getEncode(appKey+"+"+timestamp+"+"+FnaInvoiceCommon.fnaDecrypt(secret));
		//key
		params.put("app_key", appKey);
		//token
		params.put("token", token.toLowerCase());
		//当前时间戳
		params.put("timestamp", timestamp);
		//识别类型
		params.put("type", type);
		new BaseBean().writeLog("-----------------param-------------------"+params);
		URL url = new URL(interfaceurl);
		//判断是是否配置代理
		if(ProxyUtil.ifExistsProxy()){
			connection = (HttpURLConnection) url.openConnection(ProxyUtil.getProxy());
			Map<String,String> propertyMap = ProxyUtil.getProxyProperty();
			String proxyUser = propertyMap.getOrDefault("proxyUser", "");//用户名
			String proxyPwd = propertyMap.getOrDefault("proxyPwd", "");//密码
			if(!"".equals(proxyUser)&&!"".equals(proxyPwd)){
				String headerkey = "Proxy-Authorization";
				String headerValue = "Basic "+Base64.encodeBase64String((proxyUser+":"+proxyPwd).getBytes());//帐号密码用:隔开，base64加密方式
				connection.setRequestProperty(headerkey, headerValue);
			}
		}else{
			connection = (HttpURLConnection) url.openConnection();
		}
		connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=----request");
		connection.setDoOutput(true);
		connection.setDoInput(true);
		connection.setRequestProperty("Accept-Language", "zh-CN,zh;q=0.8");
		connection.setRequestProperty("Accept", "*/*");
		connection.setRequestProperty("Range", "bytes="+"");
		connection.setConnectTimeout(60000);
		connection.setReadTimeout(60000);
		connection.setRequestMethod("POST");
		StringBuffer buffer = new StringBuffer();
		for(Map.Entry<String, Object> entry:params.entrySet()){
			buffer.append("------request\r\n");
			buffer.append("Content-Disposition: form-data; name=\"");
			buffer.append(entry.getKey());
			buffer.append("\"\r\n\r\n");
			buffer.append(entry.getValue());
			buffer.append("\r\n");
		}
		outputStream = connection.getOutputStream();
		outputStream.write(buffer.toString().getBytes());
		outputStream.write(("------request\r\n").getBytes());
		outputStream.write(("Content-Disposition: form-data; name=\"image_file\";filename=\"发票1.jpg\"\r\n").getBytes());
		outputStream.write(("Content-Type: image/jpeg").getBytes());
		outputStream.write(("\"\r\n\r\n").getBytes());
		outputStream.write(bytes);
		outputStream.write(("\r\n").getBytes());
		outputStream.write(("------request--\r\n").getBytes());
		outputStream.flush();
		outputStream.close();
		StringBuffer returnInfo = new StringBuffer();
		int resultCode = connection.getResponseCode();
		if(HttpURLConnection.HTTP_OK==resultCode){
			BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(),"utf-8"));
			String line;
			while ((line = reader.readLine()) != null){
				returnInfo.append(line.trim());
			}
			reader.close();
			connection.disconnect();
			resultJsonObj.put("status", Constants.SUCCESS_CODE);
			resultJsonObj.put("returnInfo", JSONObject.fromObject(returnInfo.toString()));
		}else{
			throw new Exception("error responsecode :"+resultCode);
		}
		return resultJsonObj;
	}
    /**
     * 
     * @Title: checkshibie   
     * @Description: 校验识别接口的配置
     * @param: @param user
     * @param: @return      
     * @return: boolean      
     * @throws
     */
    public static boolean checkIdentify(User user){
    	boolean existEffectOcr=false;
    	RecordSet rs = new RecordSet();
		//如果有生效的未开启分部的ocr，直接使用
		rs.executeQuery("select * from fnainvoiceinterface where interfaceType=0 and status=1 and subIdStatus=0 ");
		if(rs.next()){
			existEffectOcr = true;
		}
		if(!existEffectOcr){
			//查询当前人员所在分部的发票云接口
			rs.executeQuery("select * from fnainvoiceinterface where interfaceType=0 and status=1 and subIdStatus=1 ");
			while (rs.next()){
				String subIds = Util.null2String(rs.getString("subIds"));
				String[] subIds_split = subIds.split(",");
				for(int i=0;i<subIds_split.length;i++){
					if(subIds_split[i].equals(user.getUserSubCompany1())){
						existEffectOcr = true;
						break;
					}
				}
				if(existEffectOcr){
					break;
				}
			}
		}
		return existEffectOcr;
    }
    
    /**
	 * 获取token
	 * @return
	 */
	public static JSONObject getToken(String client_secret,String client_id,String tokenURL) throws Exception{
		JSONObject jsonObject = new JSONObject();
		String content = "";
		String token = "";
		JSONObject tokenJson = new JSONObject();
		tokenJson.put("client_secret", client_secret);
		tokenJson.put("client_id", client_id);
		String url = tokenURL+"&client_id="+client_id+"&client_secret="+client_secret;
        CloseableHttpClient httpclient = HttpClients.createDefault();  
        //请求报文
        StringEntity s = new StringEntity(tokenJson.toString(), "UTF-8");
        s.setContentEncoding("UTF-8");
        s.setContentType("application/json");//发送json数据需要设置contentType
        
        // 构造消息头
        HttpPost post = new HttpPost(url);
		RequestConfig requestConfig = RequestConfig.custom()
		.setConnectTimeout(120000).setConnectionRequestTimeout(120000)
		.setSocketTimeout(120000).build();
		
		post.setConfig(requestConfig);// 设置超时时间
        post.setHeader("Accept-Charset", "UTF-8");
        post.setHeader("Charset", "UTF-8");
        
        post.setEntity(s); 
        
        HttpResponse res = httpclient.execute(post);
        if(res.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
        	content = EntityUtils.toString(res.getEntity());// 返回json格式
        }else {
			throw new Exception("获取token失败！");
        }
		String REPLYCODE = "0";
		String REPLYMSG = "";
	    Document document = DocumentHelper.parseText(content);
		Element rootElement = document.getRootElement();
		List<Element> rootlist = rootElement.elements();
		for(int i = 0;i<rootlist.size();i++){
			Element element = rootlist.get(i);
			if("HEAD".equals(element.getName())){
				Element SERVICE = (Element) element.elements().get(0);
				List<Element> replayList = SERVICE.elements();
				for(int j = 0;j<replayList.size();j++){
					String tag = replayList.get(j).getName();
					if("REPLYCODE".equalsIgnoreCase(tag)){
						REPLYCODE = replayList.get(j).getText();
					}
					if("REPLYMSG".equalsIgnoreCase(tag)){
						REPLYMSG = replayList.get(j).getText();
					}
				}
 			}
			if("BODY".equals(element.getName())){
				List<Element> replayList = element.elements();
				for(int j = 0;j<replayList.size();j++){
					String tag = replayList.get(j).getName();
					if("access_token".equalsIgnoreCase(tag)){
						token = replayList.get(j).getText();
					}
				}
			}
		}
		if(!"0".equals(REPLYCODE)) {
			throw new Exception(REPLYMSG);
		}
		if("".equals(token)) {
			throw new Exception("获取token失败！");
		}
		jsonObject.put("status", "0");
		jsonObject.put("token", token);
	    return jsonObject;
	}
    
	/**
	 * 获取openid
	 * @param token
	 * @return
	 */
	public static JSONObject getOpenID(String token,String openIdURL,String client_id) throws Exception{
		JSONObject jsonObject = new JSONObject();
		CloseableHttpClient httpClient = HttpClients.createDefault();
	    HttpGet get = new HttpGet(openIdURL+"&client_id="+client_id+"&access_token="+token);
	    String content = "";
	    String openId = "";
	    HttpResponse response = httpClient.execute(get);  
	    content = EntityUtils.toString(response.getEntity());
		String REPLYCODE = "0";
		String REPLYMSG = "";
	    Document document = DocumentHelper.parseText(content);
		Element rootElement = document.getRootElement();
		List<Element> rootlist = rootElement.elements();
		for(int i = 0;i<rootlist.size();i++){
			Element element = rootlist.get(i);
			if("HEAD".equals(element.getName())){
				Element SERVICE = (Element) element.elements().get(0);
				List<Element> replayList = SERVICE.elements();
				for(int j = 0;j<replayList.size();j++){
					String tag = replayList.get(j).getName();
					if("REPLYCODE".equalsIgnoreCase(tag)){
						REPLYCODE = replayList.get(j).getText();
					}
					if("REPLYMSG".equalsIgnoreCase(tag)){
						REPLYMSG = replayList.get(j).getText();
					}
				}
 			}
			if("BODY".equals(element.getName())){
				List<Element> replayList = element.elements();
				for(int j = 0;j<replayList.size();j++){
					String tag = replayList.get(j).getName();
					if("openID".equalsIgnoreCase(tag)){
						openId = replayList.get(j).getText();
					}
				}
			}
		}
		if(!"0".equals(REPLYCODE)) {
			throw new Exception(REPLYMSG);
		}
		if("".equals(openId)) {
			throw new Exception("获取openId失败！");
		}
		jsonObject.put("status", "0");
		jsonObject.put("openId", openId);
	    return jsonObject;
	}
    
    static final char HEXDIGITS[] = {
			'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
			'A', 'B', 'C', 'D', 'E', 'F'
	};
	private static String getEncode(String key) throws NoSuchAlgorithmException {
		MessageDigest messageDigest = MessageDigest.getInstance("MD5");
		try {
			messageDigest.update(key.getBytes("UTF-8"));
		} catch (UnsupportedEncodingException e) {
			messageDigest.update(key.getBytes());
		}
		byte digest[] = messageDigest.digest();
		int j = digest.length;
		char str[] = new char[j * 2];
		int k = 0;
		for(int i = 0; i < j; i++)
		{
			byte byte0 = digest[i];
			str[k++] = HEXDIGITS[byte0 >>> 4 & 0xf];
			str[k++] = HEXDIGITS[byte0 & 0xf];
		}
		return new String(str);
	}

}
